import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.swing.AbstractListModel;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;


public class TripleListBox extends JPanel {

  private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0);
  private static final String ADD_BUTTON_LABEL = "Add >>";
  private static final String REMOVE_BUTTON_LABEL = "<< Remove";

  private static final String ADD_BUTTON_LABEL2 = "<< Add";
  private static final String REMOVE_BUTTON_LABEL2 = "Remove >>";

  private static final String DEFAULT_SOURCE_CHOICE_LABEL = "List 1";
  private static final String DEFAULT_SOURCE_CHOICE_LABEL2 = "List 2";
  private static final String DEFAULT_DEST_CHOICE_LABEL = "Current Selection";

  private JLabel sourceLabel;
  private JList sourceList;
  private SortedListModel sourceListModel;

  private JLabel sourceLabel2;
  private JList sourceList2;
  private SortedListModel sourceListModel2;

  private JList destList;
  private SortedListModel destListModel;
  private JLabel destLabel;

  private JButton addButton;
  private JButton removeButton;

  private JButton addButton2;
  private JButton removeButton2;

  public TripleListBox() {
    initScreen();
  }

 public void addSourceElements(ListModel newValue) {
    fillListModel(sourceListModel, newValue);
  }
   public void addSourceElements(Object newValue[]) {
    fillListModel(sourceListModel, newValue);
  }

    public void addSourceElements2(ListModel newValue) {
    fillListModel(sourceListModel2, newValue);
  }
   public void addSourceElements2(Object newValue[]) {
    fillListModel(sourceListModel2, newValue);
  }

    public void addDestinationElements(ListModel newValue) {
    fillListModel(destListModel, newValue);
  }
    public void addDestinationElements(Object newValue[]) {
    fillListModel(destListModel, newValue);
  }

  public void setSourceElements(ListModel newValue) {
    clearSourceListModel();
    addSourceElements(newValue);
  }

    public void setSourceElements2(ListModel newValue) {
    clearSourceListModel2();
    addSourceElements2(newValue);
  }

   public void clearSourceListModel() {
    sourceListModel.clear();
  }

      public void clearSourceListModel2() {
    sourceListModel2.clear();
  }

    private void fillListModel(SortedListModel model, ListModel newValues) {
    int size = newValues.getSize();
    for (int i = 0; i < size; i++) {
      model.add(newValues.getElementAt(i));
    }
  }

      private void fillListModel(SortedListModel model, Object newValues[]) {
    model.addAll(newValues);
  }

      private void clearSourceSelected() {
    Object selected[] = sourceList.getSelectedValues();
    for (int i = selected.length - 1; i >= 0; --i) {
      sourceListModel.removeElement(selected[i]);
    }
    sourceList.getSelectionModel().clearSelection();
  }

     private void clearSourceSelected2() {
    Object selected[] = sourceList2.getSelectedValues();
    for (int i = selected.length - 1; i >= 0; --i) {
      sourceListModel2.removeElement(selected[i]);
    }
    sourceList2.getSelectionModel().clearSelection();
  }

  private void clearDestinationSelected() {
    Object selected[] = destList.getSelectedValues();
    for (int i = selected.length - 1; i >= 0; --i) {
      destListModel.removeElement(selected[i]);
    }
    destList.getSelectionModel().clearSelection();
  }

 

  
  private void initScreen() {
    setBorder(BorderFactory.createEtchedBorder());
    setLayout(new GridBagLayout());

    sourceLabel = new JLabel(DEFAULT_SOURCE_CHOICE_LABEL);
    sourceListModel = new SortedListModel();
    sourceList = new JList(sourceListModel);
    add(sourceLabel, new GridBagConstraints(0, 0, 1, 1, 0, 0,
        GridBagConstraints.CENTER, GridBagConstraints.NONE,
        EMPTY_INSETS, 0, 0));
    add(new JScrollPane(sourceList), new GridBagConstraints(0, 1, 1, 5, .5,
        1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
        EMPTY_INSETS, 0, 0));

    addButton = new JButton(ADD_BUTTON_LABEL);
    add(addButton, new GridBagConstraints(1, 2, 1, 2, 0, .25,
        GridBagConstraints.CENTER, GridBagConstraints.NONE,
        EMPTY_INSETS, 0, 0));
    addButton.addActionListener(new AddListener());
    removeButton = new JButton(REMOVE_BUTTON_LABEL);
    add(removeButton, new GridBagConstraints(1, 4, 1, 2, 0, .25,
        GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(
            0, 5, 0, 5), 0, 0));
    removeButton.addActionListener(new RemoveListener());

    destLabel = new JLabel(DEFAULT_DEST_CHOICE_LABEL);
    destListModel = new SortedListModel();
    destList = new JList(destListModel);
    add(destLabel, new GridBagConstraints(2, 0, 1, 1, 0, 0,
        GridBagConstraints.CENTER, GridBagConstraints.NONE,
        EMPTY_INSETS, 0, 0));
    add(new JScrollPane(destList), new GridBagConstraints(2, 1, 1, 5, .5,
        1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
        EMPTY_INSETS, 0, 0));


    addButton2 = new JButton(ADD_BUTTON_LABEL2);
    add(addButton2, new GridBagConstraints(3, 2, 1, 2, 0, .25,
        GridBagConstraints.CENTER, GridBagConstraints.NONE,
        EMPTY_INSETS, 0, 0));
    addButton2.addActionListener(new AddListener2());
    removeButton2 = new JButton(REMOVE_BUTTON_LABEL2);
    add(removeButton2, new GridBagConstraints(3, 4, 1, 2, 0, .25,
        GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(
            0, 5, 0, 5), 0, 0));
    removeButton2.addActionListener(new RemoveListener2());


    sourceLabel2 = new JLabel(DEFAULT_SOURCE_CHOICE_LABEL2);
    sourceListModel2 = new SortedListModel();
    sourceList2 = new JList(sourceListModel2);
    add(sourceLabel2, new GridBagConstraints(4, 0, 1, 1, 0, 0,
        GridBagConstraints.CENTER, GridBagConstraints.NONE,
        EMPTY_INSETS, 0, 0));
    add(new JScrollPane(sourceList2), new GridBagConstraints(4, 1, 1, 5, .5,
        1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
        EMPTY_INSETS, 0, 0));

  }

  public static void main(String args[]) {
    JFrame f = new JFrame("Dual List Box Tester");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    TripleListBox dual = new TripleListBox();
     String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
    String[] strings2 = { "Item 1A", "Item 2A", "Item 3A", "Item 4A", "Item 5A"};

     dual.addSourceElements(strings);
    dual.addSourceElements2(strings2);
   
    f.getContentPane().add(dual, BorderLayout.CENTER);
    f.setSize(400, 300);
    f.setVisible(true);
  }

  private class AddListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      Object selected[] = sourceList.getSelectedValues();
      addDestinationElements(selected);
      clearSourceSelected();
    }
  }

  private class RemoveListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      Object selected[] = destList.getSelectedValues();
      addSourceElements(selected);
      clearDestinationSelected();
    }
  }

    private class AddListener2 implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      Object selected[] = sourceList2.getSelectedValues();
      addDestinationElements(selected);
      clearSourceSelected2();
    }
  }

  private class RemoveListener2 implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      Object selected[] = destList.getSelectedValues();
      addSourceElements2(selected);
      clearDestinationSelected();
    }
  }

}
class SortedListModel extends AbstractListModel {

  SortedSet model;

  public SortedListModel() {
    model = new TreeSet();
  }

  public int getSize() {
    return model.size();
  }

  public Object getElementAt(int index) {
    return model.toArray()[index];
  }

  public void add(Object element) {
    if (model.add(element)) {
      fireContentsChanged(this, 0, getSize());
    }
  }

  public void addAll(Object elements[]) {
    Collection c = Arrays.asList(elements);
    model.addAll(c);
    fireContentsChanged(this, 0, getSize());
  }

  public void clear() {
    model.clear();
    fireContentsChanged(this, 0, getSize());
  }

  public boolean contains(Object element) {
    return model.contains(element);
  }

  public Object firstElement() {
    return model.first();
  }

  public Iterator iterator() {
    return model.iterator();
  }

  public Object lastElement() {
    return model.last();
  }

  public boolean removeElement(Object element) {
    boolean removed = model.remove(element);
    if (removed) {
      fireContentsChanged(this, 0, getSize());
    }
    return removed;
  }
}